package com.ma.netana.pojo;


import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.net.Inet4Address;
import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.List;

//@Data
@AllArgsConstructor
@NoArgsConstructor
public class IPPacket extends Packet {
    private static final long serialVersionUID = 6427030004078082099L;
    public byte version;
    public byte priority;
    public boolean d_flag;
    public boolean t_flag;
    public boolean r_flag;
    public byte rsv_tos;
    public short length;
    public boolean rsv_frag;
    public boolean dont_frag;
    public boolean more_frag;
    public short offset;
    public short hop_limit;
    public short protocol;
    public static final short IPPROTO_ICMP = 1;
    public static final short IPPROTO_IGMP = 2;
    public static final short IPPROTO_IP = 4;
    public static final short IPPROTO_TCP = 6;
    public static final short IPPROTO_UDP = 17;
    public static final short IPPROTO_IPv6 = 41;
    public static final short IPPROTO_HOPOPT = 0;
    public static final short IPPROTO_IPv6_Route = 43;
    public static final short IPPROTO_IPv6_Frag = 44;
    public static final short IPPROTO_IPv6_ICMP = 58;
    public static final short IPPROTO_IPv6_NoNxt = 59;
    public static final short IPPROTO_IPv6_Opts = 60;
    public int ident;
    public int flow_label;
    public InetAddress src_ip;
    public InetAddress dst_ip;
    public byte[] option;
    public List options = null;

    public void setIPv4Parameter(int priority, boolean d_flag, boolean t_flag, boolean r_flag, int rsv_tos, boolean rsv_frag, boolean dont_frag, boolean more_frag, int offset, int ident, int ttl, int protocol, InetAddress src, InetAddress dst) {
        this.version = 4;
        this.priority = (byte)priority;
        this.d_flag = d_flag;
        this.t_flag = t_flag;
        this.r_flag = r_flag;
        this.rsv_tos = (byte)rsv_tos;
        this.rsv_frag = rsv_frag;
        this.dont_frag = dont_frag;
        this.more_frag = more_frag;
        this.offset =(short) offset;
        this.ident = ident;
        this.hop_limit = (short)ttl;
        this.protocol = (short)protocol;
        if (!(src instanceof Inet6Address) && !(dst instanceof Inet6Address)) {
            this.src_ip = src;
            this.dst_ip = dst;
        } else {
            throw new IllegalArgumentException("Address must be Inet4Address");
        }
    }

    public void setIPv6Parameter(int cls, int flowlabel, int nxt_hdr, int hop_limit, InetAddress src, InetAddress dst) {
        this.version = 6;
        this.priority = (byte)cls;
        this.flow_label = flowlabel;
        this.protocol = (short)nxt_hdr;
        this.hop_limit = (short)hop_limit;
        if (!(src instanceof Inet4Address) && !(dst instanceof Inet4Address)) {
            this.src_ip = src;
            this.dst_ip = dst;
        } else {
            throw new IllegalArgumentException("Address must be Inet6Address");
        }
    }

    void setIPv4Value(byte ver, byte pri, boolean d, boolean t, boolean r, byte rsv_tos, boolean rf, boolean df, boolean mf, short offset, short len, short ident, short ttl, short proto, byte[] src, byte[] dst) {
        this.version = ver;
        this.priority = pri;
        this.d_flag = d;
        this.t_flag = t;
        this.r_flag = r;
        this.rsv_tos = rsv_tos;
        this.rsv_frag = rf;
        this.dont_frag = df;
        this.more_frag = mf;
        this.offset = offset;
        this.length = len;
        this.ident = ident;
        this.hop_limit = ttl;
        this.protocol = proto;

        try {
            this.src_ip = InetAddress.getByAddress(src);
            this.dst_ip = InetAddress.getByAddress(dst);
        } catch (UnknownHostException var18) {
        }

    }

    void setOption(byte[] option) {
        this.option = option;
    }

    void setIPv6Value(byte ver, byte v6class, int flow, short payload, byte nxt, short hlim, byte[] src, byte[] dst) {
        this.version = ver;
        this.priority = v6class;
        this.flow_label = flow;
        this.length = payload;
        this.protocol = nxt;
        this.hop_limit = hlim;

        try {
            this.src_ip = InetAddress.getByAddress(src);
            this.dst_ip = InetAddress.getByAddress(dst);
        } catch (UnknownHostException var10) {
        }

    }

    void addOptionHeader(IPv6Option header) {
        if (this.options == null) {
            this.options = new ArrayList();
        }

        this.options.add(header);
    }

    byte[] getSourceAddress() {
        return this.src_ip.getAddress();
    }

    byte[] getDestinationAddress() {
        return this.dst_ip.getAddress();
    }

    @Override
    public String toString() {
        return this.version == 4 ? super.toString() + " " + this.src_ip + "->" + this.dst_ip + " protocol(" + this.protocol + ") priority(" + this.priority + ") " + (this.d_flag ? "D" : "") + (this.t_flag ? "T" : "") + (this.r_flag ? "R" : "") + " hop(" + this.hop_limit + ") " + (this.rsv_frag ? "RF/" : "") + (this.dont_frag ? "DF/" : "") + (this.more_frag ? "MF" : "") + " offset(" + this.offset + ") ident(" + this.ident + ")" : super.toString() + " " + this.src_ip + "->" + this.dst_ip + " protocol(" + this.protocol + ") priority(" + this.priority + ") flowlabel(" + this.flow_label + ") hop(" + this.hop_limit + ")";
    }
}
